package pkg

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io"
	"log"
	"myapp/config"
	"strings"

	"github.com/elastic/go-elasticsearch/v8"
	"github.com/elastic/go-elasticsearch/v8/esapi"
)

type EsManager struct{}

type EsResult struct {
	Took int `json:"took"`
	Hits struct {
		Total struct {
			Value int `json:"value"`
		} `json:"total"`
		Hits []struct {
			Source map[string]any `json:"_source"`
		} `json:"hits"`
	} `json:"hits"`
}

type CountResponse struct {
	Count int `json:"count"`
}

var EsClient *elasticsearch.Client
var err error

func init() {
	config.Init()

	EsClient, err = elasticsearch.NewClient(elasticsearch.Config{
		Addresses: []string{config.Conf.EsUrl}, // Elasticsearch 地址
	})
	if err != nil {
		log.Fatalf("Connect Error: %s", err)
	}
}

func (es EsManager) Search(index string, musts, filters, sorts []any, from int, size int) *EsResult {
	query := map[string]any{
		"query": map[string]any{
			"bool": map[string]any{
				"must":   musts,
				"filter": filters,
			},
		},
		"sort": sorts,
		"from": from,
		"size": size,
	}

	mt, _ := json.Marshal(query)
	fmt.Println(string(mt))

	ls, err := EsClient.Search(
		EsClient.Search.WithIndex(index),
		EsClient.Search.WithBody(strings.NewReader(string(mt))),
		//EsClient.Search.WithSourceExcludes("content"),
	)

	if err != nil {
		log.Fatalf("Error Es: %s", err)
	}

	body, err := io.ReadAll(ls.Body)
	if err != nil {
		log.Fatalf("Error reading response body: %s", err)
	}

	var rs *EsResult

	err = json.Unmarshal(body, &rs)
	if err != nil {
		log.Fatalf("Error serializing document: %s", err)
	}

	return rs
}

func (es EsManager) Count(index string, musts, filters []any) *CountResponse {
	query := map[string]any{
		"query": map[string]any{
			"bool": map[string]any{
				"must":   musts,
				"filter": filters,
			},
		},
	}

	mt, _ := json.Marshal(query)
	fmt.Println(string(mt))

	req := esapi.CountRequest{
		Index: []string{index},
		Body:  strings.NewReader(string(mt)),
	}

	// 执行请求
	res, err := req.Do(context.Background(), EsClient)
	if err != nil {
		log.Fatalf("Error executing the count request: %s", err)
	}

	// 解析响应的 JSON 数据
	var countResp *CountResponse
	if err := json.NewDecoder(res.Body).Decode(&countResp); err != nil {
		log.Fatalf("Error parsing the response body: %s", err)
	}

	return countResp
}

func (es EsManager) Add(index string, docID string, doc any) bool {
	// 序列化文档为 JSON
	docJSON, err := json.Marshal(doc)
	if err != nil {
		log.Fatalf("Error serializing document: %s", err)
		return false
	}

	// 索引文档到 Elasticsearch
	res, err := EsClient.Index(
		index, // 索引名称
		bytes.NewReader(docJSON),
		EsClient.Index.WithRefresh("true"),
		EsClient.Index.WithDocumentID(docID),
	)
	if err != nil {
		log.Fatalf("Error indexing document: %s", err)
		return false
	}
	defer res.Body.Close()

	// 打印响应
	if res.IsError() {
		log.Printf("[%s] Error indexing document ID=%s", res.Status(), res.String())
		return false
	}

	return true
}

func (es EsManager) Delete(index string, docID string) bool {
	res, err := EsClient.Delete(
		index,                               // 索引名称
		docID,                               // 文档 ID
		EsClient.Delete.WithRefresh("true"), // 刷新
	)

	if err != nil {
		log.Fatalf("Error deleting document: %s", err)
		return false
	}
	defer res.Body.Close()

	if res.IsError() {
		log.Printf("Failed to delete document: %s", res.String())
		return false
	}

	return true
}
